package org.daochong.spring.controllor;

import java.util.ArrayList;
import java.util.HashSet;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
import java.util.Set;

import org.daochong.lang.BeanUtil;
import org.daochong.lang.StringUtils;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.ResponseBody;

import com.alibaba.fastjson.JSON;

import redis.clients.jedis.JedisCommands;

@Controller
@RequestMapping("/redis")
public class RedisControllor extends BaseControllor {

	private JedisCommands jedis;

	private JedisCommands getJedisCommands() {
		if (jedis == null) {
			jedis = this.getUaiFactory().getTemplate(JedisCommands.class);
		}
		return jedis;
	}

	@RequestMapping(value = "/{id}", method = RequestMethod.GET)
	@ResponseBody
	public Object load(@PathVariable String id) {
		JedisCommands jedis = getJedisCommands();
		if (!jedis.exists(id))
			return null;
		String type = jedis.type(id);
		if (type.equalsIgnoreCase("hash")) {
			return processString(getJedisCommands().hgetAll(id));
		} else if (type.equalsIgnoreCase("list")) {
			return processString(jedis.lrange(id, 0, jedis.llen(id)));
		} else if (type.equalsIgnoreCase("set")) {
			return processString(jedis.smembers(id));
		}
		return processString(getJedisCommands().get(id));
	}

	@RequestMapping(value = "/{id}/count", method = RequestMethod.GET)
	@ResponseBody
	public Object count(@PathVariable String id) {
		JedisCommands jedis = getJedisCommands();
		if (!jedis.exists(id))
			return null;
		String type = jedis.type(id);
		if (type.equalsIgnoreCase("hash")) {
			return jedis.hlen(id);
		} else if (type.equalsIgnoreCase("list")) {
			return jedis.llen(id);
		} else if (type.equalsIgnoreCase("set")) {
			return jedis.scard(id);
		}
		return 0;
	}

	@RequestMapping(value = "/keys/{id}", method = RequestMethod.GET)
	@ResponseBody
	public Object keys(@PathVariable String id) {
		JedisCommands jedis = getJedisCommands();
		if (!jedis.exists(id))
			return null;
		String type = jedis.type(id);
		if (type.equalsIgnoreCase("hash")) {
			return jedis.hkeys(id);
		}
		return new ArrayList<String>(0);

	}

	@RequestMapping(value = "/value/{id}/{key}", method = RequestMethod.GET)
	@ResponseBody
	public Object value(@PathVariable String id, @PathVariable String key) {
		JedisCommands jedis = getJedisCommands();
		if (!jedis.exists(id))
			return null;
		String type = jedis.type(id);
		if (type.equalsIgnoreCase("hash")) {
			return jedis.hget(id, key);
		} else if (type.equalsIgnoreCase("list")) {
			return processString(jedis.lindex(id, Integer.parseInt(key)));
		} 
		return null;

	}

	@RequestMapping(value = "/values/{id}", method = RequestMethod.GET)
	@ResponseBody
	public Object values(@PathVariable String id) {
		JedisCommands jedis = getJedisCommands();
		if (!jedis.exists(id))
			return null;
		String type = jedis.type(id);
		if (type.equalsIgnoreCase("hash")) {
			return jedis.hvals(id);
		} else if (type.equalsIgnoreCase("set")) {
			return jedis.smembers(id);
		} else if (type.equalsIgnoreCase("list")) {
			return jedis.lrange(id, 0, jedis.llen(id));
		}
		return new ArrayList<Object>(0);
	}

	private Object processString(String str) {
		if (str == null)
			return null;
		if (str.length() == 0) {
			return str;
		}
		String s = str.trim();
		try {
			byte[] data = StringUtils.base64Decode(s);
			return BeanUtil.unSerializable(data);
		} catch (Throwable e) {

		}
		char c1 = s.charAt(0);
		char c2 = s.charAt(s.length() - 1);
		try {
			if (c1 == '[' && c2 == ']') {
				return JSON.parseArray(s);
			} else if (c1 == '{' && c2 == '}') {
				return JSON.parseObject(s);
			}
		} catch (Throwable e) {

		}
		return str;
	}

	private Object processString(List<String> list) {
		if (list == null)
			return null;
		List<Object> re = new ArrayList<Object>();
		for (String str : list) {
			re.add(processString(str));
		}
		return re;
	}

	private Object processString(Set<String> list) {
		if (list == null)
			return null;
		Set<Object> re = new HashSet<Object>();
		for (String str : list) {
			re.add(processString(str));
		}
		return re;
	}

	private Map<String, Object> processString(Map<String, String> map) {
		if (map == null)
			return null;
		Map<String, Object> re = new LinkedHashMap<String, Object>();
		for (String key : map.keySet()) {
			re.put(key, processString(map.get(key)));
		}
		return re;
	}
}
